package com.squirrels.server.router;

import com.squirrels.server.common.constant.Constant;
import com.squirrels.server.common.constant.SystemConstant;
import com.squirrels.server.config.MongoConfig;
import com.squirrels.server.message.protobuf.Message;
import com.squirrels.server.utils.SystemUtils;
import com.squirrels.server.work.ServerWorker;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 创建者: FlyingSquirrels
 * 创建时间: 2024/7/29 17:53
 * 描述: 服务路由
 */
@Slf4j
@Component
public class ServerRouter extends SimpleChannelInboundHandler<DatagramPacket> {

    // Worker集合
    private static ConcurrentHashMap<String, ServerWorker> workers;

    // mongo连接
    @Resource private MongoConfig mongoConfig;

    // 发送对象
    private InetSocketAddress netSender;

    // 读取所有Worker 并注入数据处理 Datastore jwtutils 创建roomMannager
    @PostConstruct
    public void readConfigs() throws Exception {
        workers = SystemUtils.getUtils().readWorkers();
        mongoConfig.injectDatastore(workers);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
    }

    // 异常处理
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error(cause.getMessage());
        error(ctx,netSender,null);
    }

    // 接收数据包后分配处理Worker
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket packet) throws Exception {
        // 获取发送对象
        InetSocketAddress sender = packet.sender();
        netSender = sender;
        // 解析数据包
        Message.Entity entity = praseEntity(packet);
        if (null == entity) {
            error(channelHandlerContext,sender,null);
            return;
        }
        // 寻找处理器
        ServerWorker worker = workers.get(entity.getOperation());
        if (null == worker) {
            error(channelHandlerContext,sender,entity);
            return;
        }
        // 克隆新对象使用
        worker = worker.clone();
        // 执行处理器
        worker.exec(channelHandlerContext,sender,entity);
    }

    // 解析实体
    private Message.Entity praseEntity(DatagramPacket packet) {
        try{
            byte[] bytes = ByteBufUtil.getBytes(packet.content());
            return Message.Entity.parseFrom(bytes);
        } catch (Exception e){
            return null;
        }
    }

    // 错误提示
    private void error(ChannelHandlerContext ctx,InetSocketAddress sender,Message.Entity entity){
        Message.Entity builder = errorMsg(SystemConstant.SERVER_ERROR,entity);
        DatagramPacket data = new DatagramPacket(
                ctx.alloc().buffer().writeBytes(builder.toByteArray()),
                sender
        );
        ctx.writeAndFlush(data);
    }

    //公共错误信息
    protected Message.Entity errorMsg(Constant constant,Message.Entity entity){
        Message.Data data = Message.Data.newBuilder().setInfo(constant.getInfo()).build();
        Message.Entity res;
        if (null == entity){
            res = Message.Entity.newBuilder()
                    .setCode((int)constant.getValue())
                    .setDataType(Message.Entity.EntityType.DataType)
                    .setData(data)
                    .build();
        }else{
            res = Message.Entity.newBuilder()
                    .setOperation(entity.getOperation())
                    .setOperationBase(entity.getOperationBase())
                    .setCode((int)constant.getValue())
                    .setDataType(Message.Entity.EntityType.DataType)
                    .setData(data)
                    .build();
        }
        return res;
    }

}